#include "StdAfx.h"
#include "FaceDetection.h"

CFaceDetection::CFaceDetection(void)
{
}

CFaceDetection::~CFaceDetection(void)
{
}
static CvMemStorage* storage = 0;
static CvHaarClassifierCascade* cascade = 0;
IplImage * CFaceDetection::Face_Detect(const char *imageName)
{
	IplImage * pInpImg = cvLoadImage(imageName,1);
	CvHaarClassifierCascade * pCascade = 0;  // the face detector
	CvMemStorage * pStorage = 0;        // memory for detector to use
	CvSeq * pFaceRectSeq;              // memory-access interface

	pStorage = cvCreateMemStorage(0);
	pCascade = (CvHaarClassifierCascade *)cvLoad
		((OPENCV_ROOT"/data/haarcascades/haarcascade_frontalface_default.xml"),
		0, 0, 0 );

	// validate that everything initialized properly
	if( !pInpImg || !pStorage || !pCascade )
	{
		printf("Initialization failed");
		exit(-1);
	}

	// detect faces in image
	pFaceRectSeq = cvHaarDetectObjects
		(pInpImg, pCascade, pStorage,
		1.1,                      // increase search scale by 10% each pass
		3,                        // merge groups of three detections
		CV_HAAR_DO_CANNY_PRUNING,  // skip regions unlikely to contain a face
		cvSize(40,40));            // smallest size face to detect = 40x40


	// display detected faces
	char* name=new char[100];
	strcpy(name,imageName);

	displayDetections(pInpImg, pFaceRectSeq, name);

	// clean up and release resources
	//cvReleaseImage(&pInpImg);
	if(pCascade) cvReleaseHaarClassifierCascade(&pCascade);
	if(pStorage) cvReleaseMemStorage(&pStorage);

	return pInpImg;
}


void CFaceDetection::displayDetections(IplImage * pInpImg, CvSeq * pFaceRectSeq, char* FileName)
{
	const char * DISPLAY_WINDOW = "Haar Window";
	int i;

	// create a window to display detected faces
	cvNamedWindow(DISPLAY_WINDOW, CV_WINDOW_AUTOSIZE);

	// draw a rectangular outline around each detection
	for(i=0;i<(pFaceRectSeq? pFaceRectSeq->total:0); i++ )
	{
		CvRect* r = (CvRect*)cvGetSeqElem(pFaceRectSeq, i);
		CvPoint pt1 = { r->x, r->y };
		CvPoint pt2 = { r->x + r->width, r->y + r->height };
		cvRectangle(pInpImg, pt1, pt2, CV_RGB(0,255,0), 3, 4, 0);
		cvSetImageROI(pInpImg, *r);
		//char* FileName = argv[1];
		IplImage* dst = cvCreateImage( cvSize(92,112), pInpImg->depth, pInpImg->nChannels);
		cvResize(pInpImg, dst, CV_INTER_LINEAR);
		strcat(FileName,".pgm");
		cvSaveImage(FileName, dst); 
	}

	// display face detections
	cvShowImage(DISPLAY_WINDOW, pInpImg);
	cvWaitKey(0);
	cvDestroyWindow(DISPLAY_WINDOW);
}


const char* cascade_name =
OPENCV_ROOT"/data/haarcascades/haarcascade_frontalface_default.xml";
/* "haarcascade_profileface.xml";*/

int CFaceDetection::Face_Detect2( const char *imageName)
{
	CvCapture* capture = 0;
	IplImage *frame, *frame_copy = 0;
	int optlen = strlen("--cascade=");
	const char* input_name = imageName;

	cascade_name = OPENCV_ROOT"/data/haarcascades/haarcascade_frontalface_alt2.xml";

	cascade = (CvHaarClassifierCascade*)cvLoad( cascade_name, 0, 0, 0 );

	if( !cascade )
	{
		fprintf( stderr, "ERROR: Could not load classifier cascade\n" );
		fprintf( stderr,
			"Usage: facedetect --cascade=\"<cascade_path>\" [filename|camera_index]\n" );
		return -1;
	}
	storage = cvCreateMemStorage(0);

	if( !input_name || (isdigit(input_name[0]) && input_name[1] == '\0') )
		capture = cvCaptureFromCAM( !input_name ? 0 : input_name[0] - '0' );
	else
		capture = cvCaptureFromAVI( input_name ); 

	cvNamedWindow( "result", 1 );

	if( capture )
	{
		for(;;)
		{
			if( !cvGrabFrame( capture ))
				break;
			frame = cvRetrieveFrame( capture );
			if( !frame )
				break;
			if( !frame_copy )
				frame_copy = cvCreateImage( cvSize(frame->width,frame->height),
				IPL_DEPTH_8U, frame->nChannels );
			if( frame->origin == IPL_ORIGIN_TL )
				cvCopy( frame, frame_copy, 0 );
			else
				cvFlip( frame, frame_copy, 0 );

			FaceDetect_and_Draw( frame_copy );

			if( cvWaitKey( 10 ) >= 0 )
				break;
		}

		cvReleaseImage( &frame_copy );
		cvReleaseCapture( &capture );
	}
	else
	{
		const char* filename = input_name ? input_name : (char*)"lena.jpg";
		IplImage* image = cvLoadImage( filename, 1 );

		if( image ) 
		{
			FaceDetect_and_Draw( image );
			cvWaitKey(0);
			cvReleaseImage( &image );
		}
		else
		{
			/* assume it is a text file containing the
			list of the image filenames to be processed - one per line */
			FILE* f = fopen( filename, "rt" );
			if( f )
			{
				char buf[1000+1];
				while( fgets( buf, 1000, f ) )
				{
					int len = (int)strlen(buf);
					while( len > 0 && isspace(buf[len-1]) )
						len--;
					buf[len] = '\0';
					image = cvLoadImage( buf, 1 );
					if( image )
					{
						FaceDetect_and_Draw( image );
						cvWaitKey(0);
						cvReleaseImage( &image );
					}
				}
				fclose(f);
			}
		}

	}

	cvDestroyWindow("result");

	return 0;
}


void CFaceDetection::FaceDetect_and_Draw( IplImage* img )
{
	static CvScalar colors[] = 
	{
		{{0,0,255}},
		{{0,128,255}},
		{{0,255,255}},
		{{0,255,0}},
		{{255,128,0}},
		{{255,255,0}},
		{{255,0,0}},
		{{255,0,255}}
	};

	double scale = 1.3;
	IplImage* gray = cvCreateImage( cvSize(img->width,img->height), 8, 1 );
	IplImage* small_img = cvCreateImage( cvSize( cvRound (img->width/scale),
		cvRound (img->height/scale)),
		8, 1 );
	int i;

	cvCvtColor( img, gray, CV_BGR2GRAY );
	cvResize( gray, small_img, CV_INTER_LINEAR );
	cvEqualizeHist( small_img, small_img );
	cvClearMemStorage( storage );

	if( cascade )
	{
		double t = (double)cvGetTickCount();
		CvSeq* faces = cvHaarDetectObjects( small_img, cascade, storage,
			1.1, 2, 0/*CV_HAAR_DO_CANNY_PRUNING*/,
			cvSize(30, 30) );
		t = (double)cvGetTickCount() - t;
		printf( "detection time = %gms\n", t/((double)cvGetTickFrequency()*1000.) );
		for( i = 0; i < (faces ? faces->total : 0); i++ )
		{
			CvRect* r = (CvRect*)cvGetSeqElem( faces, i );
			CvPoint center;
			int radius;
			center.x = cvRound((r->x + r->width*0.5)*scale);
			center.y = cvRound((r->y + r->height*0.5)*scale);
			radius = cvRound((r->width + r->height)*0.25*scale);
			cvCircle( img, center, radius, colors[i%8], 3, 8, 0 );
		}
	}

	cvShowImage( "result", img );
	cvReleaseImage( &gray );
	cvReleaseImage( &small_img );
}

